package hash

import (
	"crypto/hmac"
	"gitee.com/gcom/gbox/crypto"
)

type hash struct {
	hashType crypto.Hash
}

func NewHash(hashType crypto.Hash) *hash {
	return &hash{hashType}
}

//Get gets hashed bytes with defined hashType
func (h *hash) Get(src []byte) (dst []byte, err error) {
	_, dst, err = crypto.GetHash(src, h.hashType)
	return
}

//EncodeToString gets hashed bytes with defined hashType and then encode to string
func (h *hash) EncodeToString(src []byte, encodeType crypto.Encode) (dst string, err error) {
	data, err := GetHash(src, h.hashType)
	return crypto.EncodeToString(data, encodeType)
}

type hmacHash struct {
	hashType crypto.Hash
	key      []byte
}

func NewHMAC(hashType crypto.Hash, key []byte) *hmacHash {
	return &hmacHash{hashType, key}
}

//Get gets hmac hashed bytes with defined hashType & key
func (hh *hmacHash) Get(src []byte) (dst []byte, err error) {
	h, _ := crypto.GetHashFunc(hh.hashType)
	hm := hmac.New(h, hh.key)
	hm.Write(src)
	dst = hm.Sum(nil)
	return
}

//EncodeToString gets hmac hashed bytes with defined hashType & key then encode to string
func (hh *hmacHash) EncodeToString(src []byte, encodeType crypto.Encode) (dst string, err error) {
	data, err := GetHMACHash(src, hh.hashType, hh.key)
	return crypto.EncodeToString(data, encodeType)
}

//GetHash gets hashed bytes with defined hashType
func GetHash(src []byte, hashType crypto.Hash) (dst []byte, err error) {
	_, dst, err = crypto.GetHash(src, hashType)
	return
}

//GetHashEncodeToString gets hashed bytes with defined hashType and then encode to string
func GetHashEncodeToString(encodeType crypto.Encode, src []byte, hashType crypto.Hash) (dst string, err error) {
	data, err := GetHash(src, hashType)
	return crypto.EncodeToString(data, encodeType)
}

//GetHMACHash gets hmac hashed bytes with defined hashType & key
func GetHMACHash(src []byte, hashType crypto.Hash, key []byte) (dst []byte, err error) {
	h, _ := crypto.GetHashFunc(hashType)
	hm := hmac.New(h, key)
	hm.Write(src)
	dst = hm.Sum(nil)
	return
}

//GetHMACHashEncodeToString gets hmac hashed bytes with defined hashType & key then encode to string
func GetHMACHashEncodeToString(encodeType crypto.Encode, src []byte, hashType crypto.Hash, key []byte) (dst string, err error) {
	data, err := GetHMACHash(src, hashType, key)
	return crypto.EncodeToString(data, encodeType)
}
